import { confirm } from '../src/confirm';
import { IParams } from '../src/params';
import { SaeInterface } from '../src/sae';
import * as sinon from 'sinon';
import { expect } from 'chai';
import * as step from '@flow-step/step-toolkit'
import {
    ConfirmPipelineBatchRequest,
    ConfirmPipelineBatchResponse
} from '@alicloud/sae20190506'

const params: IParams = {
    PACKAGE: '',
    APPLICATION_ID: 'app123',
    Batch: '',
    BatchWaitTime: '',
    ReleaseType: '',
    StrategyType: '',
    USE_ACR_EE: false,
    buildJobID: 0,
    domestic: false,
    minReadyInstanceType: '',
    pipelineID: 0,
    pipelineName: '',
    projectDir: '',
    regionID: 'cn-hangzhou',
    workSpace: '',
    CHANGE_ORDER_ID: '12345',
    APP_NAME: 'my-app'
};



describe('confirm', () => {
    let mockSae: SaeInterface;
    let sandbox: sinon.SinonSandbox;
    let confirmPipelineBatchStub: sinon.SinonStub;
    let addOutputStub: sinon.SinonStub;
    let addLinkStub: sinon.SinonStub;
    let runActionStub: sinon.SinonStub;

    beforeEach(() => {
        sandbox = sinon.createSandbox();
        confirmPipelineBatchStub = sandbox.stub();
        addOutputStub = sandbox.stub(step, 'addOutput');
        addLinkStub = sandbox.stub(step.interaction, 'addLink');
        runActionStub = sandbox.stub(step.interaction, 'runAction');

        mockSae = {
            confirmPipelineBatch: confirmPipelineBatchStub
        } as unknown as SaeInterface;

        process.env.NEXT_PIPELINE_ID = 'pipeline123';
    });

    afterEach(() => {
        sandbox.restore();
        delete process.env.NEXT_PIPELINE_ID;
    });

    it('should successfully confirm deployment', async () => {
        const mockResponse = new ConfirmPipelineBatchResponse({
            body: {
                code: '200',
                message: 'success'
            }
        });

        confirmPipelineBatchStub.resolves(mockResponse);

        await confirm(params, mockSae);

        expect(confirmPipelineBatchStub.calledOnce).to.be.true;
        expect(confirmPipelineBatchStub.firstCall.args[0]).to.deep.equal(new ConfirmPipelineBatchRequest({ pipelineId: 'pipeline123', confirm: true }));

        expect(runActionStub.calledOnceWith('CHECK')).to.be.true;
        expect(addOutputStub.calledWith('CHANGE_ORDER_ID=12345')).to.be.true;
        expect(addOutputStub.calledWith('APP_NAME=my-app')).to.be.true;
        expect(addLinkStub.calledOnceWith('Change Order Details','https://saenext.console.aliyun.com/cn-hangzhou/app-list/app123/micro-app/record/12345',41)).to.be.true;
    });

    it('should throw an error if NEXT_PIPELINE_ID is not set', async () => {
        delete process.env.NEXT_PIPELINE_ID;

        try {
            await confirm(params, mockSae);
            expect.fail('Expected confirm to throw an error');
        } catch (error: any) {
            expect(error.message).to.equal('NEXT_PIPELINE_ID is not set in environment variables');
        }
    });

    it('should throw an error if confirmPipelineBatch fails', async () => {
        const error = new Error('Some error occurred');
        confirmPipelineBatchStub.rejects(error);

        try {
            await confirm(params, mockSae);
            expect.fail('Expected confirm to throw an error');
        } catch (e: any) {
            expect(e.message).to.equal(`failed to confirmPipelineBatch: ${error}`);
        }
    });

    it('should throw an error if the response code is not 200', async () => {
        const mockResponse = new ConfirmPipelineBatchResponse({
            body: {
                code: '500',
                message: 'Service Error'
            }
        });

        confirmPipelineBatchStub.resolves(mockResponse);

        try {
            await confirm(params, mockSae);
            expect.fail('Expected confirm to throw an error');
        } catch (e: any) {
            expect(e.message).to.equal(`failed to continue deployment, code: ${mockResponse.body?.code}, message: ${mockResponse.body?.message}`);
        }
    });
});
